#!/usr/bin/env python
# -*- coding: utf-8 -*-

__VERSION__ = '1.0.5'
__author__ = 'rx.wen218@gmail.com'

from optparse import OptionParser
from core import sync_task
from datetime import datetime
from datetime import timedelta
from core.policy import Policy
from getpass import getpass
import logging, sys, re
from core.blogproviderfactory import BlogProviderType, BlogProviderFactory

# options passed via command line
cmdline_options = {}
# options collected interactively
interactive_options = {}

def ConfirmUpdatePostHandler(action, post):
    action_str = "add"
    if sync_task.UpdatePostAction.UPDATE == action:
        action_str = "update"
    confirm  = raw_input("%s post: %s\n (y/n) "%(action_str, post.title))
    if confirm == 'y':
        return True
    else: 
        return False

def RunInteractively(option, opt_str, value, parser, *args, **kwargs):
    print "select source blog type"
    ListSupportedBlogs()
    interactive_options['src_blog_type'] = raw_input()
    if BlogProviderType.LIVESPACE == int(interactive_options['src_blog_type']):
        interactive_options['file_path'] = raw_input("local file/folder path: ")
    else:
        interactive_options['src_account'] = raw_input("username:")
        interactive_options['src_password'] = raw_input("password:")

    print "select destination blog type"
    ListSupportedBlogs()
    interactive_options['dst_blog_type'] = raw_input()
    if BlogProviderType.LIVESPACE == int(interactive_options['dst_blog_type']):
        interactive_options['file_path'] = raw_input("local file/folder path: ")
    else:
        interactive_options['dst_account'] = raw_input("username:")
        interactive_options['dst_password'] = raw_input("password:")

    interactive_options['start_date'] = raw_input("start date (yyyy-mm-dd):")
    interactive_options['end_date'] = raw_input("end date (yyyy-mm-dd):")

def ListSupportedBlogs():
    print """
    1. blogger [www.blogger.com / www.blogspot.com]
    2. wordpress [www.wordpress.com]
    3. csdn [blog.csdn.net]
    4. live space [spaces.live.com]
    5. cnblogs [www.cnblogs.com]
    6. sina [blog.sina.com]
    """

def OptListBlogsCallback(option, opt_str, value, parser, *args, **kwargs):
    ListSupportedBlogs()
    exit(0)

def main():
    opt_parser = OptionParser(version = "%prog " + __VERSION__, 
            description = "command line tool for synchronizing posts between different blogs",
            usage = "blogporter.py [options] \n"
                    "Example: blogporter.py --src-type=1 --src-account=account1 --src-password=secret1 "
                    "--dst-type=2 --dst-account=account2 --dst-password=secret2 "
                    "--startdate=2010-01-01 -e2010-01-07 -plocal_folder/")
    opt_parser.add_option("", "--src-type", dest="src_blog_type", help="source blog type")
    opt_parser.add_option("", "--src-account", dest="src_account", help="source blog account name")
    opt_parser.add_option("", "--src-password", dest="src_password", help="source blog account password")
    opt_parser.add_option("", "--dst-type", dest="dst_blog_type", help="destination blog type")
    opt_parser.add_option("", "--dst-account", dest="dst_account", help="destination blog account name")
    opt_parser.add_option("", "--dst-password", dest="dst_password", help="destination blog account password")
    opt_parser.add_option("-s", "--startdate", dest="start_date", help="posts start date (yyyy-mm-dd), defaults to seven days before today")
    opt_parser.add_option("-e", "--enddate", dest="end_date", help="posts end date (yyyy-mm-dd)")
    opt_parser.add_option("-p", "--file-path", dest="file_path", help="file/folder path to local blog data")
    opt_parser.add_option("-i", "--interactive", action="callback", callback = RunInteractively, 
            help="run the application in interactive mode")
    opt_parser.add_option("", "--list-blogs", action="callback", callback=OptListBlogsCallback, help="list supported blogs")
    opt_parser.add_option("-v", "--verbose", action="store_true", default=False, help="verbose output [default: %default]")
    opt_parser.add_option("-q", "--quite", action="store_true", default=False, help="no output [default: %default]")
    opt_parser.add_option("-c", "--confirm", action="store_true", default=False, help="no need to confirm update[default: %default]")
    (cmdline_options, args) = opt_parser.parse_args()
    if len(sys.argv) < 2:
        opt_parser.print_help()
        exit(0)

    # merge cmdline_options with interactive_options
    # cmdline_option will be overwritten if a collision occurs
    cmdline_options.__dict__.update(interactive_options)
    
    start_date, end_date = None, None
    if cmdline_options.start_date:
        try:
            start_date = datetime.strptime(cmdline_options.start_date, '%Y-%m-%d') 
        except ValueError:
            print "invalid datetime format, should be yyyy-dd-mm, e.g., 1990-2-23"
            exit(0)

    if cmdline_options.end_date:
        try:
            end_date = datetime.strptime(cmdline_options.end_date, '%Y-%m-%d') 
        except ValueError:
            print "invalid datetime format, should be yyyy-dd-mm, e.g., 1990-2-23"
            exit(0)

    if start_date == None or end_date == None:
        default_delta = timedelta(7) # default start date to seven days before
        if start_date == None and end_date == None:
            start_date = datetime.now() - default_delta
            end_date = datetime.now()
        elif start_date == None:
            start_date = end_date - default_delta
        else:
            end_date = start_date + default_delta

    end_date = end_date.replace(hour=23,minute=59,second=59)
    if start_date >= end_date:
        print "end date (%s) should be later than start date (%s)" % (end_date, start_date)
        exit(0)

    src_password, dst_password = None, None
    if cmdline_options.src_password:
        src_password = cmdline_options.src_password
    else:
        src_password = getpass("src password: ")
        if len(src_password) == 0:
            print "password can't be null"
            exit(0)
    if cmdline_options.dst_password:
        dst_password = cmdline_options.dst_password
    else:
        dst_password = getpass("dst password (leave blank if it's the same as src password): ")
        if len(dst_password) == 0:
            # use src password as dst password if dst password isn't specified
            dst_password = src_password
#    logging.basicConfig()
    logger_handler = logging.StreamHandler(sys.stdout)
    logger_handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
    root_logger = logging.getLogger()
    # clear existing logging handlers
    for h in root_logger.handlers:
        root_logger.handlers.pop()

    root_logger.addHandler(logger_handler)
    if cmdline_options.verbose:
        root_logger.setLevel(logging.NOTSET)

    factory = BlogProviderFactory()
    try:
        src = factory.GetBlogProvider(int(cmdline_options.src_blog_type), \
                cmdline_options.src_account, src_password, \
                file_path = cmdline_options.file_path)
        dst = factory.GetBlogProvider(int(cmdline_options.dst_blog_type), \
                cmdline_options.dst_account, dst_password, \
                file_path = cmdline_options.file_path)
    except ImportError as err:
        print err
        exit(0)

    task = sync_task.SyncTask(src, dst)
    if not cmdline_options.confirm:
       task.SetBeforeUpdatePostHandler(ConfirmUpdatePostHandler)

    time_format = "%Y-%m-%d %H:%M:%S"
    print "sync posts between %s and %s" % (start_date.strftime(time_format), 
            end_date.strftime(time_format))
    task.Run(start_date, end_date)
    print "done!"

if __name__ == "__main__":
    main()
